﻿using Sharp.WeShare.Common;

namespace Sharp.WeShare.Pay
{
    public static class PayTools
    {
        /// <summary>
        /// 发起支付接口请求
        /// </summary>
        /// <typeparam name="T">请求成功后的返回实体</typeparam>
        /// <param name="entity">请求的参数集合</param>
        /// <param name="url">请求的url</param>
        /// <param name="key">支付密钥</param>
        /// <param name="certpath">证书路径，可空</param>
        /// <param name="certpwd">证书密码</param>
        /// <returns></returns>
        public static T PayRequest<T>(this BasePay entity, string url, string key, string certpath = "", string certpwd = "") where T : BasePayRes, new()
        {
            var param = Utils.EntityToDictionary(entity);//将实体转换成数据集合
            param.Add("sign", Utils.GetPaySign(param, key));//生成签名，并将签名添加到数据集
            var xml = Utils.parseXML(param);//将数据集合转换成XML
            var res = Utils.HttpPost(url, xml, certpath, certpwd);
            return XmlToEntity<T>(res, key);
        }
        /// <summary>
        /// 将返回的xml转换成对象，并校验签名，如签名校验失败，返回自定义错误信息。（注：此错误信息与微信无关，可能数据被篡改，请认真对待）
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="xml"></param>
        /// <param name="key"></param>
        /// <returns></returns>
        private static T XmlToEntity<T>(string xml, string key) where T : BasePayRes, new()
        {
            var dic = Utils.XmlToDictionary(xml);
            if (dic["return_code"] == "FAIL" || dic["result_code"] == "FAIL")
            {
                if (dic.ContainsKey("result_code"))
                {
                    return new T
                    {
                        return_code = dic["return_code"],
                        result_code = dic["result_code"],
                        err_code = dic["err_code"],
                        err_code_des = dic["err_code_des"]

                    };
                }
                return new T
                {
                    return_code = dic["return_code"]
                };
            }
            if (dic.ContainsKey("sign"))
            {
                var originalsign = dic["sign"];
                dic.Remove("sign");
                var sign = Utils.GetPaySign(dic, key);
                if (sign == originalsign)
                {
                    dic.Add("sign", sign);
                }
                else
                {
                    return new T { err_code = "自定义错误", err_code_des = "微信返回的参数签名校验失败，数据可能被篡改，原始数据为：" + xml };
                }
            }
            return Utils.DictionaryToObject<T>(dic);
        }
    }
}